package com.childenglish.controller;

import com.childenglish.entity.ParentChildRelation;
import com.childenglish.entity.SysClass;
import com.childenglish.entity.SysStudentClass;
import com.childenglish.entity.SysUser;
import com.childenglish.mapper.ParentChildRelationMapper;
import com.childenglish.mapper.SysClassMapper;
import com.childenglish.mapper.SysRoleMapper;
import com.childenglish.mapper.SysStudentClassMapper;
import com.childenglish.mapper.SysUserMapper;
import com.childenglish.controller.CaptchaController;
import com.childenglish.utils.DataEncryptionUtils;
import com.childenglish.utils.PasswordEncoderUtil;
import com.childenglish.utils.R;
import com.childenglish.utils.SecurityAuditLogger;
import com.childenglish.utils.UserDataHelper;
import com.childenglish.utils.ValidationPatterns;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import javax.validation.constraints.NotBlank;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Pattern;
import javax.validation.constraints.Size;
import javax.validation.constraints.Min;
import javax.validation.constraints.Max;
import com.childenglish.validation.PasswordMatch;
import com.childenglish.validation.ValidRole;
import com.childenglish.validation.OptionalPattern;
import com.childenglish.validation.OptionalEmail;
import com.childenglish.validation.EncryptedEmail;
import com.childenglish.validation.EncryptedPattern;
import java.time.LocalDateTime;
import java.util.*;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.subject.Subject;

@RestController
@RequestMapping("/api")
public class RegisterController {

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private SysRoleMapper sysRoleMapper;

    @Autowired
    private ParentChildRelationMapper parentChildRelationMapper;

    @Autowired
    private SysClassMapper sysClassMapper;

    @Autowired
    private SysStudentClassMapper sysStudentClassMapper;

    @Autowired
    private CaptchaController captchaController;

    /**
     * 检查用户名是否可用
     */
    @GetMapping("/check-username")
    public R checkUsername(@RequestParam String username) {
        // 用户名格式验证
        if (!ValidationPatterns.USERNAME_PATTERN.matcher(username).matches()) {
            return R.error("用户名必须为4-20位字母、数字或下划线");
        }

        SysUser user = sysUserMapper.findByUsername(username);
        return user == null ? R.ok("用户名可用") : R.error("用户名已存在");
    }

    /**
     * 用户注册主接口 - 使用 @Valid 注解进行参数校验
     */
    @PostMapping("/register")
    @Transactional
    public R register(@Valid @RequestBody RegisterRequest request, HttpServletRequest httpRequest, HttpSession session) {
        String ipAddress = SecurityAuditLogger.getClientIp(httpRequest);
        String userAgent = SecurityAuditLogger.getUserAgent(httpRequest);
        try {
            // 验证验证码（业务逻辑校验，保留）
            if (!captchaController.verifyCaptchaFromSession(session, request.getCaptcha())) {
                SecurityAuditLogger.logRegister(request.getUsername(), request.getRole(), false, ipAddress, userAgent);
                return R.error("验证码错误或已过期");
            }

            // 检查用户名是否已存在（业务逻辑校验，保留）
            SysUser existingUser = sysUserMapper.findByUsername(request.getUsername());
            if (existingUser != null) {
                return R.error("用户名已存在");
            }

            // 创建用户
            SysUser user = new SysUser();
            user.setUsername(request.getUsername().trim());
            // 使用BCrypt加密密码（先解密前端加密的密码）
            String rawPassword = UserDataHelper.decryptPassword(request.getPassword());
            user.setPassword(PasswordEncoderUtil.encode(rawPassword));
            user.setRole(request.getRole());
            user.setNickname(request.getNickname() != null ? request.getNickname().trim() : null);
            
            // 处理邮箱和手机号（加密存储）
            user.setEmail(UserDataHelper.processAndEncryptEmail(request.getEmail()));
            user.setPhone(UserDataHelper.processAndEncryptPhone(request.getPhone()));
            
            user.setCreatedTime(LocalDateTime.now());
            user.setUserType(UserDataHelper.getUserTypeByRole(request.getRole()));

            int result = sysUserMapper.insert(user);
            if (result > 0) {
                // 插入用户角色关联
                Long roleId = sysRoleMapper.findRoleIdByRoleKey(user.getRole());
                if (roleId != null) {
                    int roleResult = sysRoleMapper.insertUserRole(user.getId(), roleId);
                    if (roleResult <= 0) {
                        throw new RuntimeException("分配用户角色失败");
                    }
                } else {
                    throw new RuntimeException("未找到角色: " + user.getRole());
                }

                Map<String, Object> data = new HashMap<>();
                data.put("userId", user.getId());
                data.put("username", user.getUsername());
                data.put("role", user.getRole());
                
                // 记录注册成功日志
                SecurityAuditLogger.logRegister(user.getUsername(), user.getRole(), true, ipAddress, userAgent);
                
                return R.ok("注册成功").data(data);
            } else {
                // 记录注册失败日志
                SecurityAuditLogger.logRegister(request.getUsername(), request.getRole(), false, ipAddress, userAgent);
                return R.error("注册失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            // 记录注册异常日志
            SecurityAuditLogger.logRegister(request.getUsername(), request.getRole(), false, ipAddress, userAgent);
            return R.error("注册过程中出现错误: " + e.getMessage());
        }
    }

    /**
     * 家长注册儿童账户 - 使用 @Valid 注解进行参数校验
     */
    @PostMapping("/register-child")
    @Transactional
    public R registerChild(@Valid @RequestBody ChildRegisterRequest request) {
        try {
            // 检查家长是否存在（业务逻辑校验，保留）
            SysUser parent = sysUserMapper.findById(request.getParentId());
            if (parent == null) {
                return R.error("家长用户不存在");
            }

            // 检查儿童用户名是否已存在
            SysUser existingChild = sysUserMapper.findByUsername(request.getChildUsername());
            if (existingChild != null) {
                return R.error("儿童用户名已存在");
            }

            // 创建儿童用户
            SysUser childUser = new SysUser();
            childUser.setUsername(request.getChildUsername().trim());
            // 使用BCrypt加密密码
            childUser.setPassword(PasswordEncoderUtil.encode(request.getChildPassword()));
            childUser.setRole("child");
            childUser.setUserType("02"); // 02=幼儿
            childUser.setNickname(request.getChildNickname() != null ? request.getChildNickname().trim() : null);
            childUser.setCreatedTime(LocalDateTime.now());

            int childResult = sysUserMapper.insert(childUser);
            if (childResult <= 0) {
                return R.error("创建儿童账户失败");
            }

            // 插入儿童用户角色关联
            Long childRoleId = sysRoleMapper.findRoleIdByRoleKey("child");
            if (childRoleId != null) {
                int childRoleResult = sysRoleMapper.insertUserRole(childUser.getId(), childRoleId);
                if (childRoleResult <= 0) {
                    throw new RuntimeException("分配儿童角色失败");
                }
            } else {
                throw new RuntimeException("未找到儿童角色");
            }

            // 创建亲子关系
            ParentChildRelation relation = new ParentChildRelation();
            relation.setParentId(request.getParentId());
            relation.setChildId(childUser.getId());
            relation.setRelationType("parent");
            relation.setStatus("0");
            relation.setCreateTime(LocalDateTime.now());
            relation.setUpdateTime(LocalDateTime.now());

            int relationResult = parentChildRelationMapper.insert(relation);
            if (relationResult <= 0) {
                throw new RuntimeException("创建亲子关系失败");
            }

            // 根据年龄分配班级
            String ageRange = getAgeRange(request.getAge());
            SysClass assignedClass = sysClassMapper.findAvailableClassByAgeRange(ageRange);
            
            String assignedClassName = "未分配班级";
            Long assignedClassId = null;
            
            if (assignedClass != null) {
                assignedClassId = assignedClass.getClassId();
                assignedClassName = assignedClass.getClassName();
                
                // 创建学生班级关联
                SysStudentClass studentClass = new SysStudentClass();
                studentClass.setStudentId(childUser.getId());
                studentClass.setClassId(assignedClassId);
                studentClass.setJoinTime(LocalDateTime.now());
                studentClass.setStatus("0");
                studentClass.setCreateTime(LocalDateTime.now());
                
                int studentClassResult = sysStudentClassMapper.insert(studentClass);
                if (studentClassResult <= 0) {
                    throw new RuntimeException("分配班级失败");
                }
                
                // 更新班级当前学生数
                int newCurrentStudents = (assignedClass.getCurrentStudents() != null ? assignedClass.getCurrentStudents() : 0) + 1;
                sysClassMapper.updateCurrentStudents(assignedClassId, newCurrentStudents);
            } else {
                // 如果没有可用班级，使用默认班级名称
                assignedClassName = assignClassByAge(request.getAge());
            }

            Map<String, Object> data = new HashMap<>();
            data.put("childId", childUser.getId());
            data.put("childUsername", childUser.getUsername());
            data.put("assignedClass", assignedClassName);
            data.put("assignedClassId", assignedClassId);
            data.put("age", request.getAge());
            data.put("englishLevel", request.getEnglishLevel());
            data.put("interests", request.getInterests());

            return R.ok("儿童注册成功").data(data);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("儿童注册失败: " + e.getMessage());
        }
    }

    /**
     * 根据年龄获取年龄范围字符串
     */
    private String getAgeRange(Integer age) {
        if (age == null) {
            return "5-6岁";
        }
        if (age >= 3 && age <= 4) {
            return "3-4岁";
        } else if (age >= 5 && age <= 6) {
            return "5-6岁";
        } else if (age >= 7 && age <= 8) {
            return "7-8岁";
        } else if (age >= 9 && age <= 10) {
            return "9-10岁";
        } else {
            return "5-6岁"; // 默认
        }
    }

    /**
     * 根据年龄分配班级（返回班级名称，用于显示）
     */
    private String assignClassByAge(Integer age) {
        if (age == null) {
            return "少儿英语基础班";
        }
        if (age >= 3 && age <= 4) {
            return "幼儿英语启蒙班";
        } else if (age >= 5 && age <= 6) {
            return "少儿英语基础班";
        } else if (age >= 7 && age <= 8) {
            return "少儿英语进阶班";
        } else if (age >= 9 && age <= 10) {
            return "少儿英语提高班";
        } else {
            return "少儿英语基础班";
        }
    }

    /**
     * 验证密码强度
     */
    @PostMapping("/validate-password")
    public R validatePassword(@RequestBody PasswordRequest request) {
        String password = request.getPassword();

        if (password == null || password.trim().isEmpty()) {
            return R.error("密码不能为空");
        }

        if (password.length() < 8 || password.length() > 20) {
            return R.error("密码长度必须为8-20位");
        }

        boolean hasLetter = false;
        boolean hasNumber = false;
        boolean hasSpecial = false;

        for (char c : password.toCharArray()) {
            if (Character.isLetter(c)) {
                hasLetter = true;
            } else if (Character.isDigit(c)) {
                hasNumber = true;
            } else if ("@$!%*#?&".indexOf(c) >= 0) {
                hasSpecial = true;
            }
        }

        if (!hasLetter || !hasNumber) {
            return R.error("密码必须包含字母和数字");
        }

        // 计算密码强度
        int strength = 0;
        if (password.length() >= 8) strength++;
        if (hasLetter && hasNumber) strength++;
        if (hasSpecial) strength++;
        if (password.length() >= 12) strength++;

        String strengthLevel;
        if (strength <= 2) {
            strengthLevel = "弱";
        } else if (strength == 3) {
            strengthLevel = "中";
        } else {
            strengthLevel = "强";
        }

        Map<String, Object> data = new HashMap<>();
        data.put("strength", strengthLevel);
        data.put("score", strength);
        data.put("hasLetter", hasLetter);
        data.put("hasNumber", hasNumber);
        data.put("hasSpecial", hasSpecial);

        return R.ok("密码强度合适").data(data);
    }

    /**
     * 验证邮箱格式
     */
    @PostMapping("/validate-email")
    public R validateEmail(@RequestBody EmailRequest request) {
        String email = request.getEmail();

        if (email == null || email.trim().isEmpty()) {
            return R.ok("邮箱为空");
        }

        if (!ValidationPatterns.EMAIL_PATTERN.matcher(email).matches()) {
            return R.error("邮箱格式不正确");
        }

        return R.ok("邮箱格式正确");
    }

    /**
     * 验证手机号格式
     */
    @PostMapping("/validate-phone")
    public R validatePhone(@RequestBody PhoneRequest request) {
        String phone = request.getPhone();

        if (phone == null || phone.trim().isEmpty()) {
            return R.ok("手机号为空");
        }

        if (!ValidationPatterns.PHONE_PATTERN.matcher(phone).matches()) {
            return R.error("手机号格式不正确");
        }

        return R.ok("手机号格式正确");
    }

    /**
     * 获取班级列表
     * 如果是老师，只返回该老师所教的班级
     * 如果是管理员或其他角色，返回所有班级
     */
    @GetMapping("/classes")
    public R getClasses() {
        try {
            List<SysClass> classList;
            
            // 获取当前登录用户
            Subject subject = SecurityUtils.getSubject();
            if (subject.isAuthenticated()) {
                SysUser currentUser = (SysUser) subject.getPrincipal();
                
                // 如果是老师（userType='03'），只返回该老师所教的班级
                if (currentUser != null && "03".equals(currentUser.getUserType())) {
                    Long teacherId = currentUser.getId();
                    classList = sysClassMapper.findByTeacherId(teacherId);
                    System.out.println("老师 " + currentUser.getUsername() + " (ID: " + teacherId + ") 查询班级，返回 " + classList.size() + " 个班级");
                } else {
                    // 管理员或其他角色，返回所有班级
                    classList = sysClassMapper.findAllActive();
                    System.out.println("管理员或其他角色查询班级，返回所有 " + classList.size() + " 个班级");
                }
            } else {
                // 未登录用户，返回所有班级（保持向后兼容）
                classList = sysClassMapper.findAllActive();
                System.out.println("未登录用户查询班级，返回所有 " + classList.size() + " 个班级");
            }
            
            // 转换为前端需要的格式
            List<Map<String, Object>> classes = new ArrayList<>();
            for (SysClass sysClass : classList) {
                // 实时计算当前学生数（从学生班级关联表统计）
                int actualStudentCount = sysStudentClassMapper.countByClassId(sysClass.getClassId());
                
                Map<String, Object> classData = new HashMap<>();
                classData.put("id", sysClass.getClassId());
                classData.put("name", sysClass.getClassName());
                classData.put("classCategory", sysClass.getClassCategory());
                classData.put("ageRange", sysClass.getAgeRange());
                classData.put("studentCount", actualStudentCount); // 使用实时计算的学生数
                classData.put("maxStudents", sysClass.getMaxStudents() != null ? sysClass.getMaxStudents() : 0);
                classData.put("gradeLevel", sysClass.getGradeLevel());
                classData.put("teacherId", sysClass.getTeacherId());
                classData.put("description", sysClass.getClassDescription());
                classes.add(classData);
            }
            
            Map<String, Object> result = new HashMap<>();
            result.put("classes", classes);
            return R.ok("获取班级列表成功").data(result);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("获取班级列表失败: " + e.getMessage());
        }
    }

    /**
     * 创建班级
     */
    @PostMapping("/classes")
    public R createClass(@RequestBody Map<String, Object> classData) {
        try {
            SysClass sysClass = new SysClass();
            sysClass.setClassName((String) classData.get("name"));
            sysClass.setClassCategory((String) classData.get("classCategory"));
            sysClass.setGradeLevel((String) classData.get("gradeLevel"));
            sysClass.setAgeRange((String) classData.get("ageRange"));
            sysClass.setMaxStudents(classData.get("maxStudents") != null ? 
                Integer.parseInt(classData.get("maxStudents").toString()) : 30);
            sysClass.setCurrentStudents(0);
            sysClass.setTeacherId(classData.get("teacherId") != null ? 
                Long.parseLong(classData.get("teacherId").toString()) : null);
            sysClass.setClassDescription((String) classData.get("description"));
            sysClass.setStatus("0");
            sysClass.setCreateTime(LocalDateTime.now());
            sysClass.setUpdateTime(LocalDateTime.now());
            
            int result = sysClassMapper.insert(sysClass);
            if (result > 0) {
                return R.ok("创建班级成功").data(sysClass);
            } else {
                return R.error("创建班级失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("创建班级失败: " + e.getMessage());
        }
    }

    /**
     * 更新班级信息
     */
    @PutMapping("/classes/{classId}")
    public R updateClass(@PathVariable Long classId, @RequestBody Map<String, Object> classData) {
        try {
            SysClass existingClass = sysClassMapper.findById(classId);
            if (existingClass == null) {
                return R.error("班级不存在");
            }
            
            existingClass.setClassName((String) classData.get("name"));
            existingClass.setClassCategory((String) classData.get("classCategory"));
            existingClass.setGradeLevel((String) classData.get("gradeLevel"));
            existingClass.setAgeRange((String) classData.get("ageRange"));
            existingClass.setMaxStudents(classData.get("maxStudents") != null ? 
                Integer.parseInt(classData.get("maxStudents").toString()) : existingClass.getMaxStudents());
            // 正确处理 teacherId，允许为 null
            if (classData.get("teacherId") != null && !classData.get("teacherId").toString().trim().isEmpty()) {
                existingClass.setTeacherId(Long.parseLong(classData.get("teacherId").toString()));
            } else {
                // 如果前端没有传递 teacherId，保持原有值（可能为 null）
                existingClass.setTeacherId(existingClass.getTeacherId());
            }
            existingClass.setClassDescription((String) classData.get("description"));
            existingClass.setUpdateTime(LocalDateTime.now());
            
            int result = sysClassMapper.update(existingClass);
            if (result > 0) {
                return R.ok("更新班级成功").data(existingClass);
            } else {
                return R.error("更新班级失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("更新班级失败: " + e.getMessage());
        }
    }

    /**
     * 删除班级（软删除）
     */
    @DeleteMapping("/classes/{classId}")
    public R deleteClass(@PathVariable Long classId) {
        try {
            SysClass existingClass = sysClassMapper.findById(classId);
            if (existingClass == null) {
                return R.error("班级不存在");
            }
            
            // 检查班级中是否有学生
            int studentCount = sysStudentClassMapper.countByClassId(classId);
            if (studentCount > 0) {
                return R.error("该班级中还有 " + studentCount + " 名学生，无法删除。请先将学生转班后再删除。");
            }
            
            // 软删除：将状态设置为停用
            int result = sysClassMapper.deleteById(classId);
            if (result > 0) {
                return R.ok("删除班级成功");
            } else {
                return R.error("删除班级失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("删除班级失败: " + e.getMessage());
        }
    }

    /**
     * 测试接口：检查数据库中的学生数据
     */
    @GetMapping("/students/debug")
    public R debugStudents() {
        try {
            Map<String, Object> debugInfo = new HashMap<>();
            
            // 1. 检查所有用户
            List<SysUser> allUsers = sysUserMapper.findAll();
            debugInfo.put("totalUsers", allUsers != null ? allUsers.size() : 0);
            
            // 2. 检查学生用户（user_type='02'）
            List<SysUser> studentsByType = new ArrayList<>();
            if (allUsers != null) {
                for (SysUser user : allUsers) {
                    if (user != null && "02".equals(user.getUserType())) {
                        studentsByType.add(user);
                    }
                }
            }
            debugInfo.put("studentsByType", studentsByType.size());
            debugInfo.put("studentsByTypeList", studentsByType.stream()
                .map(u -> u.getUsername() + "(" + u.getNickname() + ")")
                .collect(java.util.stream.Collectors.toList()));
            
            // 3. 检查通过角色查询的学生
            List<SysUser> studentsByRole = sysUserMapper.findByRole("child");
            debugInfo.put("studentsByRole", studentsByRole != null ? studentsByRole.size() : 0);
            
            // 4. 检查学生班级关联
            int totalStudentClassRelations = 0;
            Map<String, Integer> classStudentCount = new HashMap<>();
            if (studentsByType != null && !studentsByType.isEmpty()) {
                for (SysUser student : studentsByType) {
                    List<SysStudentClass> relations = sysStudentClassMapper.findByStudentId(student.getId());
                    if (relations != null && !relations.isEmpty()) {
                        totalStudentClassRelations += relations.size();
                        for (SysStudentClass sc : relations) {
                            if (sc != null && sc.getClassId() != null) {
                                SysClass classInfo = sysClassMapper.findById(sc.getClassId());
                                if (classInfo != null) {
                                    String className = classInfo.getClassName();
                                    classStudentCount.put(className, 
                                        classStudentCount.getOrDefault(className, 0) + 1);
                                }
                            }
                        }
                    }
                }
            }
            debugInfo.put("totalStudentClassRelations", totalStudentClassRelations);
            debugInfo.put("classStudentCount", classStudentCount);
            
            // 5. 检查每个班级的学生数
            List<SysClass> allClasses = sysClassMapper.findAllActive();
            Map<String, Object> classInfo = new HashMap<>();
            for (SysClass c : allClasses) {
                int count = sysStudentClassMapper.countByClassId(c.getClassId());
                classInfo.put(c.getClassName(), count);
            }
            debugInfo.put("classStudentCountByAPI", classInfo);
            
            return R.ok("调试信息").data(debugInfo);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("调试失败: " + e.getMessage());
        }
    }

    /**
     * 获取学生列表（包含班级信息）
     * 如果是老师，只返回该老师所教班级的学生
     */
    @GetMapping("/students")
    public R getStudents(@RequestParam(required = false) Long classId) {
        try {
            // 获取当前登录用户，判断是否是老师
            Set<Long> allowedClassIds = null; // null 表示可以查看所有班级
            Subject subject = SecurityUtils.getSubject();
            if (subject.isAuthenticated()) {
                SysUser currentUser = (SysUser) subject.getPrincipal();
                
                // 如果是老师（userType='03'），只返回该老师所教班级的学生
                if (currentUser != null && "03".equals(currentUser.getUserType())) {
                    Long teacherId = currentUser.getId();
                    List<SysClass> teacherClasses = sysClassMapper.findByTeacherId(teacherId);
                    allowedClassIds = new HashSet<>();
                    for (SysClass cls : teacherClasses) {
                        allowedClassIds.add(cls.getClassId());
                    }
                    System.out.println("老师 " + currentUser.getUsername() + " (ID: " + teacherId + ") 查询学生，可访问的班级ID: " + allowedClassIds);
                    
                    // 如果指定了班级ID，验证该班级是否属于该老师
                    if (classId != null && !allowedClassIds.contains(classId)) {
                        return R.error("您无权访问该班级的学生信息");
                    }
                }
            }
            
            // 首先尝试通过user_type查询所有学生（更可靠）
            List<SysUser> allUsers = sysUserMapper.findAll();
            List<SysUser> allStudents = new ArrayList<>();
            for (SysUser user : allUsers) {
                if (user != null && "02".equals(user.getUserType())) {
                    allStudents.add(user);
                }
            }
            
            // 如果通过user_type查不到，再尝试通过角色查询
            if (allStudents.isEmpty()) {
                allStudents = sysUserMapper.findByRole("child");
            }
            
            System.out.println("========== 获取学生列表 ==========");
            System.out.println("查询到的学生数量: " + (allStudents != null ? allStudents.size() : 0));
            if (allStudents != null && !allStudents.isEmpty()) {
                System.out.println("所有学生用户名: " + allStudents.stream()
                    .map(s -> s.getUsername() + "(" + s.getNickname() + ", type=" + s.getUserType() + ")")
                    .collect(java.util.stream.Collectors.joining(", ")));
            } else {
                System.out.println("警告：没有查询到任何学生！");
                System.out.println("所有用户数量: " + (allUsers != null ? allUsers.size() : 0));
                if (allUsers != null && !allUsers.isEmpty()) {
                    System.out.println("所有用户的user_type: " + allUsers.stream()
                        .map(u -> u.getUsername() + "=" + u.getUserType())
                        .collect(java.util.stream.Collectors.joining(", ")));
                }
            }
            
            List<Map<String, Object>> students = new ArrayList<>();
            
            if (allStudents != null && !allStudents.isEmpty()) {
                for (SysUser student : allStudents) {
                    if (student == null || student.getId() == null) {
                        continue;
                    }
                    
                    // 查询学生所在的班级
                    List<SysStudentClass> studentClasses = sysStudentClassMapper.findByStudentId(student.getId());
                    
                    String className = "未分班";
                    Long studentClassId = null;
                    if (studentClasses != null && !studentClasses.isEmpty()) {
                        // 找到状态为'0'（在读）的班级关联
                        SysStudentClass studentClass = null;
                        for (SysStudentClass sc : studentClasses) {
                            if (sc != null && "0".equals(sc.getStatus())) {
                                studentClass = sc;
                                break;
                            }
                        }
                        // 如果没找到状态为'0'的，就用第一个
                        if (studentClass == null) {
                            studentClass = studentClasses.get(0);
                        }
                        
                        if (studentClass != null && studentClass.getClassId() != null) {
                            SysClass classInfo = sysClassMapper.findById(studentClass.getClassId());
                            if (classInfo != null) {
                                className = classInfo.getClassName();
                                studentClassId = classInfo.getClassId();
                            }
                        }
                    } else {
                        System.out.println("学生 " + student.getUsername() + " 没有分配到班级");
                    }
                    
                    // 如果指定了班级ID，只返回该班级的学生
                    if (classId != null && !classId.equals(studentClassId)) {
                        continue;
                    }
                    
                    // 如果是老师，只返回该老师所教班级的学生
                    if (allowedClassIds != null) {
                        if (studentClassId == null || !allowedClassIds.contains(studentClassId)) {
                            continue;
                        }
                    }
                    
                    // 从年龄范围推断年龄（简单处理：取范围中间值）
                    Integer age = null;
                    if (studentClassId != null) {
                        SysClass classInfo = sysClassMapper.findById(studentClassId);
                        if (classInfo != null && classInfo.getAgeRange() != null) {
                            String ageRange = classInfo.getAgeRange();
                            // 解析年龄范围，如 "3-4岁" -> 取3和4的平均值
                            try {
                                String[] parts = ageRange.replace("岁", "").split("-");
                                if (parts.length == 2) {
                                    int minAge = Integer.parseInt(parts[0].trim());
                                    int maxAge = Integer.parseInt(parts[1].trim());
                                    age = (minAge + maxAge) / 2;
                                }
                            } catch (Exception e) {
                                // 解析失败，使用默认值
                            }
                        }
                    }
                    
                    // 学习进度（暂时使用随机值，后续可以从学习记录表获取）
                    int progress = (int)(Math.random() * 100);
                    
                    Map<String, Object> studentData = new HashMap<>();
                    studentData.put("id", student.getId());
                    studentData.put("username", student.getUsername() != null ? student.getUsername() : "");
                    studentData.put("nickname", student.getNickname() != null ? student.getNickname() : "");
                    studentData.put("email", student.getEmail() != null ? student.getEmail() : "");
                    studentData.put("phone", student.getPhone() != null ? student.getPhone() : "");
                    studentData.put("className", className);
                    studentData.put("classId", studentClassId);
                    studentData.put("age", age);
                    studentData.put("progress", progress);
                    students.add(studentData);
                }
            }
            
            System.out.println("处理后的学生数量: " + students.size());
            if (!students.isEmpty()) {
                System.out.println("前3个学生信息: " + students.stream()
                    .limit(3)
                    .map(s -> s.get("username") + "->" + s.get("className"))
                    .collect(java.util.stream.Collectors.joining(", ")));
            }
            System.out.println("===================================");
            
            Map<String, Object> result = new HashMap<>();
            result.put("students", students);
            result.put("total", students.size());
            return R.ok("获取学生列表成功").data(result);
        } catch (Exception e) {
            e.printStackTrace();
            System.err.println("获取学生列表异常: " + e.getMessage());
            // 即使出错也返回空列表，而不是错误
            Map<String, Object> result = new HashMap<>();
            result.put("students", new ArrayList<>());
            result.put("total", 0);
            return R.ok("获取学生列表成功（暂无数据）").data(result);
        }
    }

    /**
     * 获取学生详情（包含基本信息及家长信息）
     */
    @GetMapping("/students/{studentId}")
    public R getStudentDetail(@PathVariable Long studentId) {
        try {
            // 获取学生基本信息
            SysUser student = sysUserMapper.findById(studentId);
            if (student == null || !"02".equals(student.getUserType())) {
                return R.error("学生不存在");
            }
            
            // 获取学生所在班级信息
            List<SysStudentClass> studentClasses = sysStudentClassMapper.findByStudentId(studentId);
            String className = null;
            Long classId = null;
            if (studentClasses != null && !studentClasses.isEmpty()) {
                SysStudentClass studentClass = studentClasses.get(0);
                classId = studentClass.getClassId();
                SysClass classInfo = sysClassMapper.findById(classId);
                if (classInfo != null) {
                    className = classInfo.getClassName();
                }
            }
            
            // 获取学生年龄（从班级年龄范围推断）
            Integer age = null;
            if (classId != null) {
                SysClass classInfo = sysClassMapper.findById(classId);
                if (classInfo != null && classInfo.getAgeRange() != null) {
                    String ageRange = classInfo.getAgeRange();
                    // 解析年龄范围，如 "3-4岁" -> 取3和4的平均值
                    try {
                        String[] parts = ageRange.replace("岁", "").split("-");
                        if (parts.length == 2) {
                            int minAge = Integer.parseInt(parts[0].trim());
                            int maxAge = Integer.parseInt(parts[1].trim());
                            age = (minAge + maxAge) / 2;
                        }
                    } catch (Exception e) {
                        // 解析失败，使用默认值
                    }
                }
            }
            
            // 获取学习进度（这里简化处理，实际应该从学习记录中计算）
            int progress = (int)(Math.random() * 100); // 暂时使用随机值，后续可以从学习记录表获取
            
            // 获取家长信息
            List<Map<String, Object>> parents = new ArrayList<>();
            List<ParentChildRelation> relations = parentChildRelationMapper.findByChildId(studentId);
            if (relations != null && !relations.isEmpty()) {
                for (ParentChildRelation relation : relations) {
                    // 兼容旧数据：如果 status 为 null 或 "0"，都认为是有效关联
                    String status = relation.getStatus();
                    if (status == null || "0".equals(status)) {
                        SysUser parent = sysUserMapper.findById(relation.getParentId());
                        if (parent != null) {
                            Map<String, Object> parentInfo = new HashMap<>();
                            parentInfo.put("id", parent.getId());
                            parentInfo.put("username", parent.getUsername());
                            parentInfo.put("nickname", parent.getNickname());
                            parentInfo.put("email", parent.getEmail());
                            parentInfo.put("phone", parent.getPhone());
                            parentInfo.put("relationType", relation.getRelationType() != null ? relation.getRelationType() : "parent");
                            parents.add(parentInfo);
                        }
                    }
                }
            }
            
            // 构建返回数据
            Map<String, Object> studentDetail = new HashMap<>();
            studentDetail.put("id", student.getId());
            studentDetail.put("username", student.getUsername());
            studentDetail.put("nickname", student.getNickname());
            studentDetail.put("email", student.getEmail());
            studentDetail.put("phone", student.getPhone());
            studentDetail.put("age", age);
            studentDetail.put("className", className);
            studentDetail.put("classId", classId);
            studentDetail.put("progress", progress);
            studentDetail.put("status", "0"); // 默认状态为正常
            studentDetail.put("createTime", student.getCreatedTime());
            studentDetail.put("parents", parents);
            
            return R.ok("获取学生详情成功").data(studentDetail);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("获取学生详情失败: " + e.getMessage());
        }
    }

    /**
     * 更新学生信息
     */
    @PutMapping("/students/{studentId}")
    public R updateStudent(@PathVariable Long studentId, @RequestBody Map<String, Object> studentData) {
        try {
            // 获取学生信息
            SysUser student = sysUserMapper.findById(studentId);
            if (student == null || !"02".equals(student.getUserType())) {
                return R.error("学生不存在");
            }
            
            // 更新学生基本信息
            if (studentData.get("nickname") != null) {
                student.setNickname((String) studentData.get("nickname"));
            }
            if (studentData.get("email") != null) {
                student.setEmail((String) studentData.get("email"));
            }
            if (studentData.get("phone") != null) {
                student.setPhone((String) studentData.get("phone"));
            }
            
            // 更新用户信息
            int result = sysUserMapper.updateUser(student);
            if (result > 0) {
                return R.ok("更新学生信息成功").data(student);
            } else {
                return R.error("更新学生信息失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return R.error("更新学生信息失败: " + e.getMessage());
        }
    }

    // 请求参数类
    @PasswordMatch(message = "两次密码输入不一致")
    public static class RegisterRequest {
        @NotBlank(message = "用户名不能为空")
        @Pattern(regexp = "^[a-zA-Z0-9_]{4,20}$", message = "用户名必须为4-20位字母、数字或下划线")
        private String username;

        @NotBlank(message = "密码不能为空")
        @Size(min = 8, max = 20, message = "密码长度必须在8-20位之间")
        @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*#?&]{8,20}$", 
            message = "密码必须包含字母和数字")
        private String password;

        @NotBlank(message = "确认密码不能为空")
        private String confirmPassword;

        @NotBlank(message = "角色不能为空")
        @ValidRole(message = "角色值不正确，必须是: admin, parent, child, teacher 之一")
        private String role;

        @OptionalPattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_]{2,20}$", 
            message = "昵称必须为2-20位汉字、字母、数字或下划线")
        private String nickname;

        @EncryptedEmail(message = "邮箱格式不正确")
        private String email;

        @EncryptedPattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确")
        private String phone;

        @NotBlank(message = "验证码不能为空")
        private String captcha;

        // getters and setters
        public String getUsername() { return username; }
        public void setUsername(String username) { this.username = username; }
        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }
        public String getConfirmPassword() { return confirmPassword; }
        public void setConfirmPassword(String confirmPassword) { this.confirmPassword = confirmPassword; }
        public String getRole() { return role; }
        public void setRole(String role) { this.role = role; }
        public String getNickname() { return nickname; }
        public void setNickname(String nickname) { this.nickname = nickname; }
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
        public String getPhone() { return phone; }
        public void setPhone(String phone) { this.phone = phone; }
        public String getCaptcha() { return captcha; }
        public void setCaptcha(String captcha) { this.captcha = captcha; }
    }

    @PasswordMatch(password = "childPassword", confirmPassword = "confirmPassword", message = "两次密码输入不一致")
    public static class ChildRegisterRequest {
        @NotNull(message = "家长ID不能为空")
        private Long parentId;

        @NotBlank(message = "儿童用户名不能为空")
        @Pattern(regexp = "^[a-zA-Z0-9_]{4,20}$", message = "儿童用户名必须为4-20位字母、数字或下划线")
        private String childUsername;

        @NotBlank(message = "儿童密码不能为空")
        @Size(min = 8, max = 20, message = "密码长度必须在8-20位之间")
        @Pattern(regexp = "^(?=.*[A-Za-z])(?=.*\\d)[A-Za-z\\d@$!%*#?&]{8,20}$", 
            message = "密码必须包含字母和数字")
        private String childPassword;

        @NotBlank(message = "确认密码不能为空")
        private String confirmPassword;

        @OptionalPattern(regexp = "^[\\u4e00-\\u9fa5a-zA-Z0-9_]{2,20}$", 
            message = "儿童昵称必须为2-20位汉字、字母、数字或下划线")
        private String childNickname;

        @NotNull(message = "年龄不能为空")
        @Min(value = 3, message = "年龄不能小于3岁")
        @Max(value = 14, message = "年龄不能大于14岁")
        private Integer age;

        @NotBlank(message = "英语水平不能为空")
        private String englishLevel;

        @Size(max = 100, message = "兴趣爱好不能超过100个字符")
        private String interests;

        // getters and setters
        public Long getParentId() { return parentId; }
        public void setParentId(Long parentId) { this.parentId = parentId; }
        public String getChildUsername() { return childUsername; }
        public void setChildUsername(String childUsername) { this.childUsername = childUsername; }
        public String getChildPassword() { return childPassword; }
        public void setChildPassword(String childPassword) { this.childPassword = childPassword; }
        public String getConfirmPassword() { return confirmPassword; }
        public void setConfirmPassword(String confirmPassword) { this.confirmPassword = confirmPassword; }
        public String getChildNickname() { return childNickname; }
        public void setChildNickname(String childNickname) { this.childNickname = childNickname; }
        public Integer getAge() { return age; }
        public void setAge(Integer age) { this.age = age; }
        public String getEnglishLevel() { return englishLevel; }
        public void setEnglishLevel(String englishLevel) { this.englishLevel = englishLevel; }
        public String getInterests() { return interests; }
        public void setInterests(String interests) { this.interests = interests; }
    }

    public static class PasswordRequest {
        private String password;
        public String getPassword() { return password; }
        public void setPassword(String password) { this.password = password; }
    }

    public static class EmailRequest {
        private String email;
        public String getEmail() { return email; }
        public void setEmail(String email) { this.email = email; }
    }

    public static class PhoneRequest {
        private String phone;
        public String getPhone() { return phone; }
        public void setPhone(String phone) { this.phone = phone; }
    }
}